/////////////////////////////////////////////////////////////////////////////
// Name:        ax_textinputdialog.cpp
// Purpose:     
// Author:      Julian Smart
// Modified by: 
// Created:     01/04/2009 14:48:08
// RCS-ID:      
// Copyright:   
// Licence:     New BSD License
/////////////////////////////////////////////////////////////////////////////

#include "wx/wx.h"

////@begin includes
////@end includes

#include "ax/ax_textinputdialog.h"
#include "ax/ax_speech.h"

#include "ax/ax_textctrl.h"

////@begin XPM images
////@end XPM images


/*
 * AxTextInputDialog type definition
 */

IMPLEMENT_DYNAMIC_CLASS( AxTextInputDialog, wxDialog )


/*
 * AxTextInputDialog event table definition
 */

BEGIN_EVENT_TABLE( AxTextInputDialog, wxDialog )

////@begin AxTextInputDialog event table entries
    EVT_INIT_DIALOG( AxTextInputDialog::OnInitDialog )

    EVT_TEXT( wxID_ANY, AxTextInputDialog::OnAnyTextUpdated )

////@end AxTextInputDialog event table entries

END_EVENT_TABLE()


/*
 * AxTextInputDialog constructors
 */

AxTextInputDialog::AxTextInputDialog()
{
    Init();
}

AxTextInputDialog::AxTextInputDialog( wxWindow* parent,
        const wxString& message, const wxString& caption, const wxString& defaultValue,
        const wxPoint& pos, const wxSize& size, long style)
{
    Init();
    Create(parent, message, caption, defaultValue, pos, size, style);
}


/*
 * AxTextInputDialog creator
 */

bool AxTextInputDialog::Create( wxWindow* parent,
        const wxString& message, const wxString& caption, const wxString& defaultValue,
        const wxPoint& pos, const wxSize& size, long style)
{
    m_disableEvents = true;

    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
    wxDialog::Create( parent, wxID_ANY, caption, pos, size, style );

    CreateControls(defaultValue, message);
    if (GetSizer())
    {
        GetSizer()->SetSizeHints(this);
    }
    Centre();

    m_disableEvents = false;
    return true;
}


/*
 * AxTextInputDialog destructor
 */

AxTextInputDialog::~AxTextInputDialog()
{
////@begin AxTextInputDialog destruction
////@end AxTextInputDialog destruction
}


/*
 * Member initialisation
 */

void AxTextInputDialog::Init()
{
    m_speech = NULL;

    m_disableEvents = false;

////@begin AxTextInputDialog member initialisation
    m_descriptionCtrl = NULL;
    m_valueCtrl = NULL;
////@end AxTextInputDialog member initialisation
}


/*
 * Control creation for AxTextInputDialog
 */

void AxTextInputDialog::CreateControls(const wxString& defaultValue, const wxString& message)
{
    long textControlStyle = 0;

    if (GetWindowStyle() & axTEXTDIALOG_MULTILINE)
        textControlStyle |= wxTE_MULTILINE;

////@begin AxTextInputDialog content construction
    AxTextInputDialog* itemDialog1 = this;

    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
    itemDialog1->SetSizer(itemBoxSizer2);

    wxBoxSizer* itemBoxSizer3 = new wxBoxSizer(wxVERTICAL);
    itemBoxSizer2->Add(itemBoxSizer3, 1, wxGROW|wxALL, 5);

    m_descriptionCtrl = new wxStaticText( itemDialog1, wxID_STATIC, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
    m_descriptionCtrl->Wrap(250);
    itemBoxSizer3->Add(m_descriptionCtrl, 0, wxALIGN_LEFT|wxALL, 5);

    m_valueCtrl = new AxTextCtrl( itemDialog1, wxID_ANY, _T(""), wxDefaultPosition, wxSize(280, -1), textControlStyle );
    itemBoxSizer3->Add(m_valueCtrl, 0, wxGROW|wxALL, 5);

    wxStdDialogButtonSizer* itemStdDialogButtonSizer6 = new wxStdDialogButtonSizer;

    itemBoxSizer3->Add(itemStdDialogButtonSizer6, 0, wxGROW|wxALL, 5);
    wxButton* itemButton7 = new wxButton( itemDialog1, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 );
    itemButton7->SetDefault();
    itemStdDialogButtonSizer6->AddButton(itemButton7);

    wxButton* itemButton8 = new wxButton( itemDialog1, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
    itemStdDialogButtonSizer6->AddButton(itemButton8);

    itemStdDialogButtonSizer6->Realize();

    // Set validators
    m_valueCtrl->SetValidator( wxGenericValidator(& m_value) );
    // Connect events and objects
    m_valueCtrl->Connect(wxID_ANY, wxEVT_CHAR, wxKeyEventHandler(AxTextInputDialog::OnChar), NULL, this);
////@end AxTextInputDialog content construction

    if (GetWindowStyle() & axTEXTDIALOG_MULTILINE)
    {
        m_valueCtrl->SetSize(280, 180);
        itemBoxSizer3->SetItemMinSize(m_valueCtrl, 280, 180);
    }

    m_descriptionCtrl->SetLabel(message);
    m_value = defaultValue;
    m_valueCtrl->SetFocus();
}

void AxTextInputDialog::SetShortcutManager(wxShortcutManager* shortcuts)
{
    m_valueCtrl->SetShortcutManager(shortcuts);
}

void AxTextInputDialog::SetSpeech(AxSpeech* speech)
{
    m_speech = speech;
    m_valueCtrl->SetSpeech(speech);
}

/*
 * Should we show tooltips?
 */

bool AxTextInputDialog::ShowToolTips()
{
    return true;
}

/*
 * Get bitmap resources
 */

wxBitmap AxTextInputDialog::GetBitmapResource( const wxString& name )
{
    // Bitmap retrieval
////@begin AxTextInputDialog bitmap retrieval
    wxUnusedVar(name);
    return wxNullBitmap;
////@end AxTextInputDialog bitmap retrieval
}

/*
 * Get icon resources
 */

wxIcon AxTextInputDialog::GetIconResource( const wxString& name )
{
    // Icon retrieval
////@begin AxTextInputDialog icon retrieval
    wxUnusedVar(name);
    return wxNullIcon;
////@end AxTextInputDialog icon retrieval
}

void AxTextInputDialog::SpeakCurrentText(bool initialView)
{
    wxString value = m_valueCtrl->GetValue();

    if (m_speech)
    {
        AxSpeechEvent speechEvent;
        speechEvent.SetSpeechEventType(AxSpeechEventText);
        speechEvent.SetVerbosityLevel(2);

        if (initialView)
        {
            speechEvent.SetText(m_descriptionCtrl->GetLabel());
            m_speech->EmitSpeech(speechEvent);
        }

        speechEvent.SetText(value + wxT(".\n"));
        m_speech->EmitSpeech(speechEvent);
    }
}

/*!
 * wxEVT_INIT_DIALOG event handler for wxID_ANY
 */

void AxTextInputDialog::OnInitDialog( wxInitDialogEvent& WXUNUSED(event) )
{
    SpeakCurrentText(true /* initial view */);
}


/*!
 * wxEVT_COMMAND_TEXT_UPDATED event handler for wxID_ANY
 */

void AxTextInputDialog::OnAnyTextUpdated( wxCommandEvent& event )
{
    if (m_disableEvents)
        return;
    if (event.GetId() != m_valueCtrl->GetId())
        return;
    
    // TODO: speak changed value in idle time
}

/*!
 * wxEVT_CHAR event handler for wxID_ANY
 */

void AxTextInputDialog::OnChar( wxKeyEvent& event )
{
    if (m_speech)
    {
        // TESTING
        wxChar ch = m_valueCtrl->GetTextEventHandler()->GetChar(1);
        wxString str;
        if (ch != 0)
            str += ch;

        long from, to;
        wxString nextWord, previousWord, thisWord;
        long pos = m_valueCtrl->GetInsertionPoint();

        long previousWordPos = m_valueCtrl->GetTextEventHandler()->FindNextWordPosition(pos, -1);
        if (previousWordPos != -1)
        {
            if (m_valueCtrl->GetTextEventHandler()->GetWord(previousWordPos, from, to, previousWord))
            {
                wxLogDebug(wxT("Previous word: ") + previousWord);
            }
        }
        long nextWordPos = m_valueCtrl->GetTextEventHandler()->FindNextWordPosition(pos, 1);
        if (nextWordPos != -1)
        {
            m_valueCtrl->GetTextEventHandler()->GetWord(nextWordPos, from, to, nextWord);
            wxLogDebug(wxT("Next word: ") + nextWord);
        }
        long thisWordPos = m_valueCtrl->GetTextEventHandler()->FindNextWordPosition(pos, 0);
        if (thisWordPos != -1)
        {
            m_valueCtrl->GetTextEventHandler()->GetWord(thisWordPos , from, to, thisWord);
            wxLogDebug(wxT("This word: ") + thisWord);
        }
#if 0
        wxString value;
        long i;
        for (i = 0; i < m_valueCtrl->GetLastPosition(); i++)
        {
            value += m_valueCtrl->GetTextEventHandler()->GetChar(i);
        }
#endif
#if 0
        // TODO: other keys.
        if (wxIsalnum(event.GetKeyCode()))
        {
            wxString text;
            text += (wxChar) event.GetKeyCode();
            AxSpeechEvent speechEvent;
            speechEvent.SetSpeechEventType(AxSpeechEventGeneralText);
            speechEvent.SetVerbosityLevel(2);
            speechEvent.SetText(text);
            m_speech->EmitSpeech(speechEvent);
        }
#endif
    }

    event.Skip();
}

